import java.util.Scanner;
import java.util.Random;

public class Main {

    /**
    判断年份是否为闰年
     */
    public static void leapYear() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入年份：");

        int year = scanner.nextInt();

        if (year % 4 == 0) {
            if (year % 100 == 0) {
                if (year % 400 == 0) {
                    System.out.println(year + "年是闰年");
                } else {
                    System.out.println(year + "不年是闰年");
                }
            } else {
                System.out.println(year + "是闰年");
            }
        } else {
            System.out.println(year + "不年是闰年");
        }

        scanner.close();
    }

    /**
    判断成绩是`优秀`、`良好`、`中等`、`及格`、`不及格`
     */
    public static void grade() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入分数：");

        int score = scanner.nextInt();

        if (90 <= score && score <= 100) {
            System.out.println(score + "是优秀");
        } else if (80 <= score && score < 90) {
            System.out.println(score + "是良好");
        } else if (70 <= score && score < 80) {
            System.out.println(score + "是中等");
        } else if (60 <= score && score < 70) {
            System.out.println(score + "是及格");
        } else if (0 <= score && score < 60) {
            System.out.println(score + "是不及格");
        }

        scanner.close();
    }

    /**
    摄氏度、华氏度的转换
     */
    public static void convCF() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入0是摄氏转华氏度，输入1是华氏转摄氏度：");

        int mode = scanner.nextInt();

        if (mode == 0) {
            System.out.print("输入摄氏度：");
            double cDegree = scanner.nextDouble();
            double fDegree = 32 + cDegree * 1.8;
            System.out.printf("%.2f摄氏度 = %.2f华氏度", cDegree, fDegree);
        } else {
            System.out.print("输入华氏度：");
            double fDegree = scanner.nextDouble();
            double cDegree = (fDegree - 32) * 5 / 9;
            System.out.printf("%.2f华氏度 = %.2f摄氏度", fDegree, cDegree);
        }

        scanner.close();
    }

    /**
    输出九九乘法表
     */
    public static void multiplicationTable() {
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.printf("%dx%d=%d\t", j, i, i * j);
            }
            System.out.println();
        }
    }

    /**
    求 1 ~ n 的和
     */
    public static void sum1ToN() {
        Scanner scanner = new Scanner(System.in);
        int sum = 0;

        System.out.print("输入n：");

        int n = scanner.nextInt();

        // 如果使用 for 循环方式，请注释掉 while 循环方式
        for (int i = 1; i <= n; i++) {
            sum += i;
        }

//        // 如果使用 while 循环方式，请注释掉 for 循环方式
//        while (n > 0) {
//            sum += n;
//            n--;
//        }

        System.out.printf("1 ~ %d之和：%d", n, sum);

        scanner.close();
    }

    /**
    输出 1 ~ n 所有能被 3 整除的数
     */
    public static void divisibleBy3() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入n：");

        int n = scanner.nextInt();
        int c = 0;

        for (int i = 1; i <= n; i++) {
            if (i % 3 == 0) {
                System.out.print(i + "\t");
                if (c++ == 9) {
                    c = 0;
                    System.out.println();
                }
            }
        }

        scanner.close();
    }

    /**
    输出 100 ~ 999 所有水仙花数
     */
    public static void narcissisticNumber() {
        for (int i = 1; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                for (int k = 0; k < 10; k++) {
                    if (i * 100 + j * 10 + k == Math.pow(i, 3) + Math.pow(j, 3) + Math.pow(k, 3)) {
                        System.out.print(i * 100 + j * 10 + k + " ");
                    }
                }
            }
        }
    }

    /**
    输出 1 ~ n 所有质数
     */
    public static void primeNumber() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入n：");

        int n = scanner.nextInt();

        for (int i = 2; i <= n; i++) {
            boolean isPrime = true;
            for (int j = 2; j <= Math.abs(Math.pow(i, 0.5)); j++) {
                if (i % j == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                System.out.print(i + " ");
            }
        }

        scanner.close();
    }

    /**
    猜数字游戏
     */
    public static void numberGuess() {
        Scanner scanner = new Scanner(System.in);
        Random random = new Random();
        int r = random.nextInt(100);
        System.out.println("数字已生成");

        while (true) {
            System.out.print("1 ~ 100 猜一个数字：");

            int g = scanner.nextInt();

            if (g == r) {
                System.out.println("猜对了");
                break;
            } else if (g < r) {
                System.out.println("小了");
            } else {
                System.out.println("大了");
            }
        }

        scanner.close();
    }

    /**
    输出斐波那契数列 - for 循环
     */
    public static void fibonacciFor() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入n：");

        int n = scanner.nextInt();

        if (n <= 2) {
            System.out.println(1);
        } else {
            int prev1 = 1, prev2 = 1;
            int sum = 0;
            for (int i = 3; i <= n; i++) {
                sum = prev1 + prev2;
                prev1 = prev2;
                prev2 = sum;
            }
            System.out.println(sum);
        }

        scanner.close();
    }

    /**
    输出斐波那契数列 - 递归
     */
    public static int fibonacciRecursion(int n) {
        if (n > 2) {
            return fibonacciRecursion(n - 1) + fibonacciRecursion(n - 2);
        }
        return 1;
    }

    /**
    输出斐波那契数列 - 调用递归
     */
    public static void fibonacci() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入n：");

        int n = scanner.nextInt();

        int r = fibonacciRecursion(n);

        System.out.println(r);

        scanner.close();
    }

    /**
    计算阶乘 - for 循环
     */
    public static void factorialFor() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入n：");

        int n = scanner.nextInt();

        int f = 1;

        for (int i = 1; i <= n; i++) {
            f *= i;
        }

        System.out.println(f);

        scanner.close();
    }

    /**
    计算阶乘 - 递归
     */
    public static int factorialRecursion(int n) {
        if (n == 1) {
            return 1;
        }
        return n * factorialRecursion(n - 1);
    }

    /**
    计算阶乘 - 调用递归
     */
    public static void factorial() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入n：");

        int n = scanner.nextInt();

        int f = factorialRecursion(n);

        System.out.println(f);

        scanner.close();
    }

    /**
    统计字符串中英文字母、数字、空格的数量
     */
    public static void stringStatistic() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入字符串，只包含英文字母、数字、空格：");

        String s = scanner.nextLine();

        int letters = 0;
        int digits = 0;
        int spaces = 0;

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (Character.isLetter(c)) {
                letters++;
            } else if (Character.isDigit(c)) {
                digits++;
            } else if (c == ' ') {
                spaces++;
            }
        }

        System.out.printf("字母有%d个\n", letters);
        System.out.printf("数字有%d个\n", digits);
        System.out.printf("空格有%d个", spaces);

        scanner.close();
    }

    /**
    检查一个字符串是否为回文
     */
    public static void palindrome() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入字符串：");

        String s = scanner.nextLine();

        boolean isPalindrome = true;

        for (int i = 0; i < s.length() / 2; i++) {
            if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
                isPalindrome = false;
                break;
            }
        }

        System.out.printf("字符串%s回文", (isPalindrome ? "是":"不是"));

        scanner.close();
    }

    /**
    数组逆序输出
     */
    public static void reverseArray() {
        int[] numbers = randomInitIntArray(30, 0, 10);

        int head = 0, tail = numbers.length - 1;
        while (head < tail) {
            int temp = numbers[head];
            numbers[head] = numbers[tail];
            numbers[tail] = temp;
            head++;
            tail--;
        }

        printArray(numbers);
    }

    /**
    移动 0 至数组末尾
     */
    public static void move0ToEnd() {
        int[] numbers = randomInitIntArray(30, 0, 10);

        int head = 0, tail = numbers.length - 1;
        boolean isHeadZero = false, isTailPos = false;
        while (head < tail) {
            if (numbers[head] != 0) {
                head++;
            } else {
                isHeadZero = true;
            }

            if (numbers[tail] == 0) {
                tail--;
            } else {
                isTailPos = true;
            }

            if (isHeadZero && isTailPos) {
                numbers[head] = numbers[tail];
                numbers[tail] = 0;
                isHeadZero = false;
                isTailPos = false;
            }
        }

        printArray(numbers);
    }

    /**
    数组的轮转
     */
    public static void rotateArray() {
        int[] numbers = randomInitIntArray(30, 0, 10);
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入数组轮转的位置：");

        int m = scanner.nextInt();

        int head = 0;
        int tail = m - 1;
        while (head < tail) {
            int temp = numbers[head];
            numbers[head] = numbers[tail];
            numbers[tail] = temp;
            head++;
            tail--;
        }

        head = m;
        tail = numbers.length - 1;
        while (head < tail) {
            int temp = numbers[head];
            numbers[head] = numbers[tail];
            numbers[tail] = temp;
            head++;
            tail--;
        }

        head = 0;
        tail = numbers.length - 1;
        while (head < tail) {
            int temp = numbers[head];
            numbers[head] = numbers[tail];
            numbers[tail] = temp;
            head++;
            tail--;
        }

        printArray(numbers);

        scanner.close();
    }

    /**
    最长公共前缀
     */
    public static void maxCommonPrefix() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入第1个字符串：");
        String s1 = scanner.nextLine();
        System.out.print("输入第2个字符串：");
        String s2 = scanner.nextLine();

        int i = 0;
        while (s1.charAt(i) == s2.charAt(i)) {
            System.out.print(s1.charAt(i));
            i++;
        }

        System.out.println(i > 0 ? "" : "没有公共前缀");

        scanner.close();
    }

    /**
    合并两个有序数组
     */
    public static void mergeArray() {
        int[] array1 = randomInitIntArray(10, 0, 10);
        int[] array2 = randomInitIntArray(20, 0, 10);

        bubbleSort(array1);
        bubbleSort(array2);

        System.out.print("排序后的array1：");
        printArray(array1);
        System.out.print("排序后的array2：");
        printArray(array2);

        int[] array = new int[array1.length + array2.length];

        int i = 0, i1 = 0, i2 = 0;
        while(i < array.length) {
            if (i1 >= array1.length) {
                array[i] = array2[i2];
                i2++;
            } else if (i2 >= array2.length) {
                array[i] = array1[i1];
                i1++;
            } else if (array1[i1] <= array2[i2]) {
                array[i] = array1[i1];
                i1++;
            } else {
                array[i] = array2[i2];
                i2++;
            }
            i++;
        }

        printArray(array);
    }

    /**
    二维数组对角线元素求和
     */
    public static void sumDiagonal() {
        int[][] matrix = randomInitIntMatrix(10, 10, 0, 10);

        int sum = 0;

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (i == j) {
                    sum += matrix[i][j];
                }
            }
        }

        System.out.println("矩阵对角线之和为：" + sum);
    }

    /**
    矩阵转置（二维数组行列互换）
     */
    public static void transposition() {
        int[][] matrix1 = randomInitIntMatrix(3, 4, 0, 10);
        int[][] matrix2 = randomInitIntMatrix(4, 3, 0, 1);

        for (int i = 0; i < matrix1.length; i++) {
            for (int j = 0; j < matrix1[0].length; j++) {
                matrix2[j][i] = matrix1[i][j];
            }
        }

        System.out.println("转置后的矩阵：");
        printMatrix(matrix2);
    }

    public static void main(String[] args) {
//        leapYear();
//        grade();
//        convCF();
//        multiplicationTable();
//        sum1ToN();
//        divisibleBy3();
//        narcissisticNumber();
//        primeNumber();
//        numberGuess();
//        fibonacciFor();
//        fibonacci();
//        factorialFor();
//        factorial();
//        stringStatistic();
//        palindrome();
//        reverseArray();
//        move0ToEnd();
//        rotateArray();
//        maxCommonPrefix();
//        mergeArray();
//        sumDiagonal();
//        transposition();
    }

    /**
     * 随机生成 int 数组
     * @param length: int (数组长度)
     * @param floor: int (数组中元素值的下限)
     * @param ceiling: int (数组中元素值的上限)
     * @return : int[] (初始化完成的数组)
     */
    public static int[] randomInitIntArray(int length, int floor, int ceiling) {
        Random random = new Random();
        int[] array = new int[length];

        for (int i = 0; i < length; i++) {
            array[i] = random.nextInt(ceiling - floor) + floor;
        }

        System.out.print("随机int数组：");
        printArray(array);

        return array;
    }

    /**
     * 随机生成2维 int 数组
     * @param m: int (2维数组的行数)
     * @param n: int (2维数组的列数)
     * @param floor: int (数组中元素值的下限)
     * @param ceiling: int (数组中元素值的上限)
     * @return : int[][] (初始化完成的2维数组)
     */
    public static int[][] randomInitIntMatrix(int m, int n, int floor, int ceiling) {
        Random random = new Random();
        int[][] matrix = new int[m][n];

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                matrix[i][j] = random.nextInt(ceiling - floor) + floor;
            }
        }

        System.out.println("随机2维int数组：");
        printMatrix(matrix);

        return matrix;
    }

    /**
     * 打印 int 数组
     * @param array: int[] (要打印的int数组)
     */
    public static void printArray(int[] array) {
        for (int e : array) {
            System.out.print(e + " ");
        }
        System.out.println();
    }

    /**
     * 打印2维 int 数组
     * @param matrix: int[][] (要打印的2维int数组)
     */
    public static void printMatrix(int[][] matrix) {
        for (int[] array : matrix) {
            printArray(array);
        }
    }


    /**
     * 冒泡排序
     * @param array: int[] (要排序的int数组)
     */
    public static void bubbleSort(int[] array) {
        int n = array.length;
        boolean swapped;
        for (int i = 0; i < n - 1; i++) {
            swapped = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    // 交换 array[j+1] 和 array[j]
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    swapped = true;
                }
            }
            // 如果没有元素交换，说明数组已经排序好
            if (!swapped) break;
        }
    }
}